﻿// <copyright file="CategoryTree.cs" company="Auros Ltd.">
//     Copyright (c) Auros Ltd. All rights reserved.
// </copyright>

namespace Auros.Categorisation.WebControls
{
    using System.Collections.Generic;
    using System.Linq;
    using System.Web.UI;
    using System.Web.UI.HtmlControls;
    using System.Web.UI.WebControls;
    using Auros.Categorisation.Data;

    /// <summary>
    /// Class that represents the category tree control. This control lists categories hierarchically with associated check boxes.
    /// </summary>
    public class CategoryTree : WebControl, INamingContainer
    {
        private int[] selectedItems;

        /// <summary>
        /// Gets or sets the selected categories.
        /// </summary>
        /// <value>The selected categories.</value>
        public int[] SelectedCategories
        {
            get
            {
                // Get all checked items.
                this.selectedItems = this.GetCheckedCategoryIDs().ToArray();

                return this.selectedItems;
            }

            set
            {
                this.selectedItems = value;
            }
        }

        /// <summary>
        /// Gets or sets the root ID.
        /// </summary>
        /// <value>The root ID.</value>
        public int RootID { get; set; }

        /// <summary>
        /// Called by the ASP.NET page framework to notify server controls that use composition-based implementation to create any child controls they contain in preparation for posting back or rendering.
        /// </summary>
        protected override void CreateChildControls()
        {
            this.Controls.Clear();

            this.BuildCategoryLevel(this, this.RootID);
        }

        /// <summary>
        /// Gets the checked category IDs.
        /// </summary>
        /// <returns>Enumerable of category IDs.</returns>
        private IEnumerable<int> GetCheckedCategoryIDs()
        {
            foreach (var item in ControlHelpers.GetControlsByTypeRecursive<CheckBox>(this).Where(c => c.Checked))
            {
                int catId;

                if (int.TryParse(item.Attributes["value"], out catId))
                    yield return catId;
            }
        }

        /// <summary>
        /// Generates the checkbox controls for each of the categories under a specified parent.
        /// </summary>
        /// <param name="parentControl">Control which the checkboxes should be added to.</param>
        /// <param name="parentId">ID of the parent category.</param>
        private void BuildCategoryLevel(Control parentControl, int parentId)
        {
            HtmlGenericControl unorderedList = null;
            Category[] categories = null;

            if (parentId > 0)
                categories = new CategoryRepository().GetCategories(parentId)
                    .OrderBy(c => c.SortOrder)
                    .ToArray();
            else
                categories = new CategoryRepository().GetRootCategories()
                    .OrderBy(c => c.SortOrder)
                    .ToArray();

            if (categories != null && categories.Length > 0)
            {
                unorderedList = new HtmlGenericControl("ul");
                unorderedList.Style.Add("list-style", "none");
                unorderedList.Style.Add("padding", "2px 0 2px 10px");
            }

            // Create checkboxes for each of the categories at this level.
            foreach (var category in categories)
            {
                HtmlGenericControl listItem = new HtmlGenericControl("li");
                HtmlGenericControl toggleAnchor = new HtmlGenericControl("a");
                toggleAnchor.InnerText = "+";

                //HtmlImage toggleImage = new HtmlImage();
                //toggleImage.Alt = "Expand";
                //toggleImage.Src = umbraco.IO.IOHelper.ResolveUrl(umbraco.IO.SystemDirectories.Umbraco) + "/Plugins/Categorisation/Images/plus.gif";

                CheckBox checkbox = new CheckBox();
                checkbox.Text = category.LocalizedName;
                checkbox.Attributes["value"] = category.ID.ToString();
                checkbox.Attributes["title"] = category.LocalizedDescription;
                checkbox.Enabled = category.Selectable;

                // Check selected categories.
                if (this.selectedItems != null)
                    checkbox.Checked = category.Selectable && this.selectedItems.Contains(category.ID);

                listItem.Controls.Add(checkbox);
                unorderedList.Controls.Add(listItem);

                // Build next sub-level.
                if (category.HasChildren)
                    this.BuildCategoryLevel(listItem, category.ID);
            }

            // If the unordered list has been instantiated, add it to the parent collection.
            if (unorderedList != null)
                parentControl.Controls.Add(unorderedList);
        }
    }
}